#include <jni.h>
#include <string>
#include <android/log.h>

#define XLOGD(...) __android_log_print(ANDROID_LOG_DEBUG,"audioEffect",__VA_ARGS__)
#define XLOGI(...) __android_log_print(ANDROID_LOG_INFO,"audioEffect",__VA_ARGS__)
#define XLOGE(...) __android_log_print(ANDROID_LOG_ERROR,"audioEffect",__VA_ARGS__)

extern "C" JNIEXPORT jstring JNICALL
Java_com_kk_audioeffect_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

#include <thread>
#include "AudioEffect.h"

extern "C"
JNIEXPORT void JNICALL
Java_com_kk_audioeffect_MainActivity_testAudio(JNIEnv *env, jobject thiz) {
    // TODO: implement testAudio()

    std::thread th = std::thread([](){

        audio_effect::BassEffect* bassEffect = new audio_effect::BassEffect(44100);

        float data1 [] = {1,2,3,4,5,6};
        bassEffect->process(data1,data1,sizeof(data1)/sizeof(float));

        float data2 [] = {1,2,3,4,5,6};
        bassEffect->setBass(12.0);
        bassEffect->process(data2,data2,sizeof(data2)/sizeof(float));




    });

    th.detach();
}

#include "AudioConvert.h"
#include "Equalizer.h"

audio_effect::VirtualBass sVirtualBass;
static audio_effect::BassEffect s_bassEffect(44100);


static audio_effect::EqualizerEffect sEqualizerEffect(44100);




static float * pCacheBuffer = new float [1024*8];



//audio_effect::LowPassFilter sLowPassFilter(44100,200,0.0);


CEqualizer s_Equalizer;

std::mutex s_BiQuadlock;

audio_effect::BiQuad* s_BiQuad = nullptr;



audio_effect::VirtualBass *virtualBass  = nullptr;
extern "C"
JNIEXPORT void JNICALL
Java_com_kk_audioeffect_PCMPlayer_native_1bass(JNIEnv *env, jclass clazz, jfloat bass) {
    // TODO: implement native_bass()
    //s_bassEffect.setBass(bass);
    //sVirtualBass.setStrength(bass);

    //sEqualizerEffect.update(bass,10);
    XLOGI("------------------- bass:%f",bass);
    std::lock_guard<std::mutex> lock(s_BiQuadlock);
//
//    if(s_BiQuad!= nullptr)
//    {
//        delete s_BiQuad;
//        s_BiQuad = nullptr;
//    }
//    if(s_BiQuad== nullptr)
//    {
//        s_BiQuad = new audio_effect::BiQuad(audio_effect::BiQuad::LOW_SHELF,bass,100, 44100,100, true);
//    }

}

extern "C"
JNIEXPORT jint JNICALL
Java_com_kk_audioeffect_PCMPlayer_native_1process(JNIEnv *env, jclass clazz, jbyteArray bytes,
                                                  jint len) {
    // TODO: implement native_process()




    std::lock_guard<std::mutex> lock(s_BiQuadlock);

    jbyte* pBytes =  env->GetByteArrayElements(bytes, NULL);


   // s_Equalizer.process((short*)pBytes, len/2, 1);
    audio::AudioConvert::convert_signed16_tof32((std::int16_t*)pBytes, len/2, pCacheBuffer);

//    for (int i = 0; i < len/2; i++)
//    {
//        if(s_BiQuad!= nullptr)
//        {
//            pCacheBuffer[i] = s_BiQuad->process(pCacheBuffer[i]);
//        }
//    }
   // s_bassEffect.process(pCacheBuffer, pCacheBuffer,len/2);
//    sVirtualBass.process(pCacheBuffer, pCacheBuffer, len/2);
    sEqualizerEffect.process(pCacheBuffer, pCacheBuffer, len/2);

    audio::AudioConvert::convert_f32_to_signed16(pCacheBuffer,len/2, (std::int16_t*)pBytes);
    env->ReleaseByteArrayElements(bytes, pBytes,NULL);
    return 0;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_kk_audioeffect_PCMPlayer_native_1upate_1bands_1prem(JNIEnv *env, jclass clazz,
                                                             jint band_index, jfloat db) {
    // TODO: implement native_upate_bands_prem()

   // sEqualizerEffect.update(band_index, db);

   // s_Equalizer.upate(band_index, db);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_kk_audioeffect_PCMPlayer_native_1init(JNIEnv *env, jclass clazz, jint samplate) {
    // TODO: implement native_init()

    std::lock_guard<std::mutex> lock(s_BiQuadlock);

    if(s_BiQuad== nullptr)
    {
        s_BiQuad = new audio_effect::BiQuad(audio_effect::BiQuad::PEAKING,5.0,100, 44100,100, false);
    }

    EQSettings settings;
    s_Equalizer.init(&settings, samplate);

    XLOGI("-------------");

    audio_effect::test();
}
extern "C"
JNIEXPORT void JNICALL
Java_com_kk_audioeffect_PCMPlayer_native_1upate_1preset(JNIEnv *env, jclass clazz, jstring preset) {
    // TODO: implement native_upate_preset()


    const char* pStr =   (char*)env->GetStringUTFChars(preset, nullptr);
    sEqualizerEffect.updatePreset(pStr);
    env->ReleaseStringUTFChars(preset, pStr);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_kk_audioeffect_PCMPlayer_native_1amp(JNIEnv *env, jclass clazz, jfloat db) {
    // TODO: implement native_amp()
    sEqualizerEffect.updateAmp(db);
}